package com.foo.designpattern.flyweight.SimplexFlyweight;

import junit.framework.TestCase;

/**
 * com.foo.designpattern.flyweight.SimplexFlyweight
 * Created with IntelliJ IDEA.
 * Created by jiang on 2016-05-23 16:21.
 *
 * @Description 测试类：享元模式(flyweight)--单纯享元模式
 * 享元模式：Flyweight在拳击比赛中指最轻量级，即"羽量级"，这里翻译为"享元模式"是因为这样更能反映模式的用意。
 * 享元模式是对象的结构模式，享元模式以共享的方式高效地支持大量的细粒度对象。
 * <p/>
 * 享元对象的结构：
 * 享元模式采用一个共享来避免大量拥有相同内容对象的开销。这种开销最常见、最直观的就是内存的消耗。
 * 享元对象能做到共享的关键是区分内蕴状态(Internal State)和外蕴状态(External State)。
 * 一个内蕴状态是存储在享元对象内部的，并且不会随环境的改变而有所不同。因此，一个享元可以具有内蕴状态并可以共享。
 * 一个外蕴状态是随环境的改变而改变的、不可以共享的。享元对象的外蕴状态必须由客户端保存，并在享元对象被创建后，
 * 在需要使用的时候再传入到享元对象内部。外蕴状态不可以影响享元对象的内蕴状态，它们是相互独立的。
 * 享元模式可以分成单纯享元模式和复合享元模式两种形式。
 * <p/>
 * 本例是单纯享元模式
 * 在单纯的享元模式中，所有的享元对象都是可以共享的。
 * 单纯享元模式所涉及到的角色如下：
 * 1、抽象享元(Flyweight)角色：给出一个抽象接口，以规定出所有具体享元角色需要实现的方法。
 * 2、具体享元(ConcreteFlyweight)角色：实现抽象享元角色所规定出的接口。如果有内蕴状态的话，必须负责为内蕴状态提供磁盘空间。
 * 3、享元工厂(FlyweightFactory)角色：本角色负责创建和管理享元角色。本角色必须保证享元对象可以被系统适当地共享。
 * 当一个客户端调用一个享元对象的时候，享元工厂角色会检查系统中是否已经有一个符合要求的享元对象。
 * 如果已经有了，享元工厂角色就应当提供这个已有的享元对象；
 * 如果系统中没有一个适当的享元对象的话，享元工厂角色就应当创建一个合适的享元对象。
 */

public class SimplexFlyweightTestCase extends TestCase {
    public void testSimplexFlyweight() {
        System.out.println("= = = = ↓↓↓单纯享元模式，测试开始↓↓↓ = = = =");

        FlyWeightFactory factory = new FlyWeightFactory();

        /**
         * 当客户端需要单纯享元对象的时候，需要调用享元工厂的factory()方法，
         * 并传入所需的单纯享元对象的内蕴状态，由工厂方法产生所需要的享元对象。
         */
        Flyweight flyweight = factory.factory(new Character('a'));
        flyweight.operation("First Call");

        flyweight = factory.factory(new Character('b'));
        flyweight.operation("Second Call");

        /**
         * 虽然客户端申请了三个享元对象，但是实际上创建的享元对象只有两个，这就是共享的含义。
         */
        flyweight = factory.factory(new Character('a'));
        flyweight.operation("Third Call");

        System.out.println("= = = = ↑↑↑单纯享元模式，测试结束↑↑↑ = = = =");
    }
}
